<?php

class AuthItemController extends CController {

/**
 * @var string specifies the default action to be 'list'.
 */
    public $defaultAction='list';

    /**
     * @var CActiveRecord the currently loaded data model instance.
     */
    private $_model;
    /**
     * Assigns roles to a user
     *
     * @param int $userid The user's id
     * @param String $roles The roles to assign
     * @param String $bizRules Not used yet
     * @param String $data Not used yet
     */
    private function _assignUser($userid,$roles,$bizRules,$data) {
        if($userid) {
            $auth = Yii::app()->authManager;
    /* @var $auth CDbAuthManager */
            foreach ($roles as $role) {
                $auth->assign($role, $userid,$bizRules,$data);
            }
        }
    }
    /**
     * Revokes roles from a user
     * @param int $userid The user's id
     * @param String $roles The roles to revoke
     */
    private function _revokeUser($userid,$roles) {
        if($userid) {
            $auth = Yii::app()->authManager;
    /* @var $auth CDbAuthManager */
            foreach ($roles as $role) {
                $auth->revoke($role, $userid);
            }
        }
    }

    /**
     * Assigns child items to a parent item
     * @param String $parent The parent item
     * @param String $children The child items
     */
    private function _assignChild($parent,$children) {
        if($parent) {
            $auth = Yii::app()->authManager;
    /* @var $auth CDbAuthManager */
            foreach ($children as $child) {
                $auth->addItemChild($parent, $child);
            }
        }
    }
    /**
     * Revokes child items from a parent item
     * @param String $parent The parent item
     * @param String $children The child items
     */
    private function _revokeChild($parent,$children) {
        if($parent) {
            $auth = Yii::app()->authManager;
    /* @var $auth CDbAuthManager */
            foreach ($children as $child) {
                $auth->removeItemChild($parent, $child);
            }
        }
    }

    /**
     * @return array action filters
     */
    public function filters() {
        return array(
            'accessControl', // perform access control for CRUD operations
        );
    }

    /**
     * Specifies the access control rules.
     * This method is used by the 'accessControl' filter.
     * @return array access control rules
     */
    public function accessRules() {
        return array(
            array('allow', // allow admin user to perform 'admin' action
                  'actions'=>array('assign', 'assignments', 'autocomplete', 'confirm', 'create', 'delete', 'getOpers', 'getRoles', 'getTasks', 'install', 'list', 'manage', 'show', 'showAssignments', 'update'),
                  'roles'=>array('super_admin')
            ),
            array('deny',  // deny all users
                'users'=>array('*')
            )
        );
    }

    /**
     * The assignment action
     * First checks if the user is authorized to perform this action
     * Then initializes the needed variables for the assign view.
     * If there's a post back it performs the assign action
     */
    public function actionAssign() {

        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser) || !Helper::isAuthorizer()) {
            $userid = isset($_POST[Yii::app()->getModule('srbac')->userclass][$this->module->userid]) ?
                $_POST[Yii::app()->getModule('srbac')->userclass][$this->module->userid] :
                "";

            //Init values
            $model = AuthItem::model();
            $data['userAssignedRoles'] = array();
            $data['userNotAssignedRoles'] = array();
            $data['roleAssignedTasks'] = array();
            $data['roleNotAssignedTasks'] = array();
            $data['taskAssignedOpers'] = array();
            $data['taskNotAssignedOpers'] = array();
            $data["assign"] = array("disabled"=>true);
            $data["revoke"] = array("disabled"=>true);
            $this->_setMessage("");

            $auth = Yii::app()->authManager;
     /* @var $auth CDbAuthManager */
            $authItemAssignName = isset($_POST['AuthItem']['assign']['name']) ?
                $_POST['AuthItem']['assign']['name'] : "";
            $assBizRule = isset($_POST['Assignments']['bizrule']) ?
                $_POST['Assignments']['bizrule'] : "";
            $assData = isset($_POST['Assignments']['data']) ?
                $_POST['Assignments']['data'] : "";

            $authItemRevokeName = isset($_POST['AuthItem']['revoke']['name']) ?
                $_POST['AuthItem']['revoke']['name'] : "";
            $authItemName = isset($_POST['AuthItem']['name']) ? $_POST['AuthItem']['name'] : "";

            $assItemName = isset($_POST['Assignments']['itemname']) ? $_POST['Assignments']['itemname'] : "";

            $assignRoles = Yii::app()->request->getParam('assignRoles',0);
            $revokeRoles = Yii::app()->request->getParam('revokeRoles',0);
            $assignTasks = isset($_GET['assignTasks']) ? $_GET['assignTasks'] : 0;
            $revokeTasks = isset($_GET['revokeTasks']) ? $_GET['revokeTasks'] : 0;
            $assignOpers = isset($_GET['assignOpers']) ? $_GET['assignOpers'] : 0;
            $revokeOpers = isset($_GET['revokeOpers']) ? $_GET['revokeOpers'] : 0;

            if($assignRoles && is_array($authItemAssignName)) {
                $this->_assignUser($userid,$authItemAssignName,$assBizRule,$assData);
                $this->_setMessage($this->module->tr->translate('srbac','Role(s) Assigned'));
            } else if($revokeRoles && is_array($authItemRevokeName)) {
                    $this->_revokeUser($userid,$authItemRevokeName);
                    $this->_setMessage($this->module->tr->translate('srbac','Role(s) Revoked'));
                } else if($assignTasks && is_array($authItemAssignName)) {
                        $this->_assignChild($authItemName,$authItemAssignName);
                        $this->_setMessage($this->module->tr->translate('srbac','Task(s) Assigned'));
                    } else if($revokeTasks && is_array($authItemRevokeName)) {
                            $this->_revokeChild($authItemName,$authItemRevokeName);
                            $this->_setMessage($this->module->tr->translate('srbac','Task(s) Revoked'));
                        }else if($assignOpers && is_array($authItemAssignName)) {
                                $this->_assignChild($assItemName,$authItemAssignName);
                                $this->_setMessage($this->module->tr->translate('srbac','Operation(s) Assigned'));
                            } else if($revokeOpers && is_array($authItemRevokeName)) {
                                    $this->_revokeChild($assItemName,$authItemRevokeName);
                                    $this->_setMessage( $this->module->tr->translate('srbac','Operation(s) Revoked'));
                                }
            //If not ajax show the assign page
            if(!Yii::app()->request->isAjaxRequest) {
                $this->render('assign',array(
                    'model'=>$model,
                    'message'=>$message,
                    'userid'=>$userid,
                    'active'=>$active,
                    'data'=>$data,
                ));
            } else {
            // assign to user show the user tab
                if($userid != "") {
                    $this->_getTheRoles();
                }
                else if($assignTasks != 0 || $revokeTasks != 0) {
                        $this->_getTheTasks();
                    }
                    else if($assignOpers != 0 || $revokeOpers != 0) {
                            $this->_getTheOpers();
                        }
            }
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    /**
     * Used by Ajax to get the roles of a user when he is selected in the Assign
     * roles to user tab
     */
    public function actionGetRoles() {
        $this->_setMessage("");
        $this->_getTheRoles();
    }

    private function _getTheRoles() {
        $model = new AuthItem();
        $userid = $_POST[Yii::app()->getModule('srbac')->userclass][$this->module->userid];
        $data['userAssignedRoles'] = Helper::getUserAssignedRoles($userid);
        $data['userNotAssignedRoles'] = Helper::getUserNotAssignedRoles($userid);
        if($data['userAssignedRoles'] == array()) {
            $data['revoke'] = array("name"=>"revokeUser","disabled"=>true);
        } else {
            $data['revoke'] = array("name"=>"revokeUser");
        }
        if($data['userNotAssignedRoles'] == array()) {
            $data['assign'] = array("name"=>"assignUser","disabled"=>true);
        } else {
            $data['assign'] = array("name"=>"assignUser");
        }
        $this->renderPartial('tabViews/userAjax',
            array('model'=>$model,'userid'=>$userid,'data'=>$data,'message'=>$this->_getMessage()),
            false,true);
    }

    /**
     * Used by Ajax to get the tasks of a role when it is selected in the Assign
     * tasks to roles tab
     */
    public function actionGetTasks() {
        $this->_setMessage("");
        $this->_getTheTasks();
    }

    private function _getTheTasks() {
        $model = new AuthItem();
        $name = $_POST["AuthItem"]["name"];
        $data['roleAssignedTasks']  = Helper::getRoleAssignedTasks($name);
        $data['roleNotAssignedTasks'] = Helper::getRoleNotAssignedTasks($name);
        if($data['roleAssignedTasks'] == array()) {
            $data['revoke'] = array("name"=>"revokeTask","disabled"=>true);
        } else {
            $data['revoke'] = array("name"=>"revokeTask");
        }
        if($data['roleNotAssignedTasks'] == array()) {
            $data['assign'] = array("name"=>"assignTasks","disabled"=>true);
        } else {
            $data['assign'] = array("name"=>"assignTasks");
        }
        $this->renderPartial('tabViews/roleAjax',
            array('model'=>$model,'name'=>$name,'data'=>$data,'message'=>$this->_getMessage()),false,true);

    }

    /**
     * Used by Ajax to get the operations of a task when he is selected in the Assign
     * operations to tasks tab
     */
    public function actionGetOpers() {
        $this->_setMessage("");
        $this->_getTheOpers();
    }

    private function _getTheOpers() {
        $model = new AuthItem();
        $name = $_POST["Assignments"]["itemname"];
        $data['taskAssignedOpers']  = Helper::getTaskAssignedOpers($name);
        $data['taskNotAssignedOpers'] = Helper::getTaskNotAssignedOpers($name);
        if($data['taskAssignedOpers'] == array()) {
            $data['revoke'] = array("name"=>"revokeOpers","disabled"=>true);
        } else {
            $data['revoke'] = array("name"=>"revokeOpers");
        }
        if($data['taskNotAssignedOpers'] == array()) {
            $data['assign'] = array("name"=>"assignOpers","disabled"=>true);
        } else {
            $data['assign'] = array("name"=>"assignOpers");
        }
        $this->renderPartial('tabViews/taskAjax',
            array('model'=>$model,'name'=>$name,'data'=>$data,'message'=>$this->_getMessage()),false,true);

    }

    /**
     * Shows a particular model.
     */
    public function actionShow() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $this->renderPartial('manage/show',array('model'=>$this->loadAuthItem()),false,true);
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    /**
     * Creates a new model.
     * If creation is successful, the browser will be redirected to the 'show' page.
     */
    public function actionCreate() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $model=new AuthItem;
            if(isset($_POST['AuthItem'])) {
                $model->attributes=$_POST['AuthItem'];
                try {
                    $model->save();
                    Yii::app()->user->setFlash('updateSuccess',"'".$model->name."' saved successfully");
                    $this->renderPartial('manage/update',array('model'=>$model));
                }catch (CDbException $exc ) {
                    Yii::app()->user->setFlash('updateError',"'Error while creating '".$model->name."'.<br />Possible there's already an item with the same name");
                    $this->renderPartial('manage/create',array('model'=>$model));
                }


            } else {
                $this->renderPartial('manage/create',array('model'=>$model));
            }
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    /**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'show' page.
     */
    public function actionUpdate() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $model=$this->loadAuthItem();
            $message = "";
            if(isset($_POST['AuthItem'])) {
                $model->oldName = isset($_POST["oldName"]) ?  $_POST["oldName"] : $_POST["name"];
                $model->attributes=$_POST['AuthItem'];
                if($model->save()) {
                    Yii::app()->user->setFlash('updateSuccess',"'".$model->name."' saved successfully");
                } else {

                }
            }
            $this->renderPartial('manage/update',array('model'=>$model));

        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'list' page.
     */
    public function actionDelete() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            if(Yii::app()->request->isAjaxRequest) {
                $this->loadAuthItem()->delete();
                $this->processAdminCommand();

                $criteria=new CDbCriteria;

                $pages=new CPagination(AuthItem::model()->count($criteria));
                $pages->pageSize=$this->module->pageSize;
                $pages->applyLimit($criteria);

                $sort=new CSort('AuthItem');
                $sort->applyOrder($criteria);

                $models=AuthItem::model()->findAll($criteria);
                $path = $this->module->getBasePath()."/views/authItem/manage/images/";
                $images = Helper::getImages($path);

                Yii::app()->user->setFlash('updateName',"Updating list");
                $this->renderPartial('manage/show',array(
                    'models'=>$models,
                    'pages'=>$pages,
                    'sort'=>$sort,
                    'images'=>$images,
                    'deleted'=>true,
                    ),false,true);
            }
            else {
                throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
            }
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    public function actionConfirm() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $this->renderPartial('manage/show',
                array('model'=>$this->loadAuthItem(),'delete'=>true),
                false,true);
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    /**
     * Lists all models.
     */
    public function actionList() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
        // Get selected type
            $selectedType =
                Yii::app()->request->getParam('selectedType',
                Yii::app()->user->getState("selectedType"));
            Yii::app()->user->setState("selectedType",$selectedType);

            //Get selected name
            $selectedName =
                Yii::app()->request->getParam('name',
                Yii::app()->user->getState("selectedName"));
            Yii::app()->user->setState("selectedName",$selectedName);

            if(!Yii::app()->request->isAjaxRequest) {
                Yii::app()->user->setState("currentPage",Yii::app()->request->getParam('page',0)-1);

            }
            $criteria=new CDbCriteria;
            $criteria->condition = "1";
            if($selectedName != "") {
                $criteria->condition .= " AND name LIKE '%".$selectedName."%'";
            }
            if($selectedType != "") {
                $criteria->condition .= " AND type = ".$selectedType;

            }
            $pages=new CPagination(AuthItem::model()->count($criteria));
            $pages->pageSize=$this->module->pageSize;
            $pages->applyLimit($criteria);
            $pages->route = "manage";
            $pages->setCurrentPage(Yii::app()->user->getState("currentPage"));
            $models=AuthItem::model()->findAll($criteria);
            $path = $this->module->getBasePath()."/views/authItem/manage/images/";
            $images = Helper::getImages($path);
            $this->renderPartial('manage/list',array(
                'models'=>$models,
                'pages'=>$pages,
                'images'=>$images,
                ),false,true);
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }


    /**
     * Installs srbac only in debug mode
     */
    public function actionInstall() {
        if($this->module->debug) {
            $action = Yii::app()->getRequest()->getParam("action","");
            $demo = Yii::app()->getRequest()->getParam("demo",0);
            if($action) {
                $error = Helper::install($action,$demo);
                if($error == 1) {
                    $this->render('install/overwrite', array("demo"=>$demo));
                } else if($error == 0) {
                        $this->render('install/success', array("demo"=>$demo));
                    } else if($error == 2) {
                            $this->render('install/error', array("demo"=>$demo));
                        }
            } else {
                $this->render('install/install');
            }
        } else {
            throw new CHttpException(403,'Srbac must be in debug mode for the installation',1);
        }
    }

    public function actionManage() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $this->processAdminCommand();
            if(Yii::app()->request->isAjaxRequest || isset($_GET['page'])) {
                $selectedType = Yii::app()->request->getParam('selectedType',Yii::app()->user->getState("selectedType"));

            } else {
                $selectedType = "";
            }
            Yii::app()->user->setState("selectedType",$selectedType);
            $criteria=new CDbCriteria;
            if($selectedType != "") {
                $criteria->condition = "type = ".$selectedType;

            }

            if(!Yii::app()->request->isAjaxRequest) {
                Yii::app()->user->setState("currentPage",Yii::app()->request->getParam('page',0)-1);

            }


            $pages=new CPagination(AuthItem::model()->count($criteria));
            $pages->route = "manage";
            $pages->pageSize=$this->module->pageSize;
            $pages->applyLimit($criteria);
            $pages->setCurrentPage(Yii::app()->user->getState('currentPage'));

            $sort=new CSort('AuthItem');
            $sort->applyOrder($criteria);

            $models=AuthItem::model()->findAll($criteria);
            $path = $this->module->getBasePath()."/views/authItem/manage/images/";
            $images = Helper::getImages($path);

            if(Yii::app()->request->isAjaxRequest) {
                echo $filterName;
                $this->renderPartial('manage/list',array(
                    'models'=>$models,
                    'pages'=>$pages,
                    'sort'=>$sort,
                    'images'=>$images,
                    ),false,true);
            } else {

                $this->render('manage/manage',array(
                    'models'=>$models,
                    'pages'=>$pages,
                    'sort'=>$sort,
                    'images'=>$images,
                ));
            }
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    public function actionAutocomplete() {
        $criteria = new CDbCriteria();
        $criteria->condition = "name LIKE '%".Yii::app()->request->getParam('q')."%'";
        $items = AuthItem::model()->findAll($criteria);
        foreach ($items as $item) {
            $valuesArray[] = $item->name;
        }
        echo join("\n",$valuesArray);

    }

    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     * @param integer the primary key value. Defaults to null, meaning using the 'id' GET variable
     */
    public function loadAuthItem($id=null) {
        if($this->_model===null) {
            if($id!==null || isset($_REQUEST['id']))
                $this->_model=AuthItem::model()->findbyPk($id!==null ? $id : $_REQUEST['id']);
            if($this->_model===null)
                throw new CHttpException(404,'The requested page does not exist.');
        }
        return $this->_model;
    }

    /**
     * Executes any command triggered on the admin page.
     */
    protected function processAdminCommand() {
        if(isset($_POST['command'], $_POST['id']) && $_POST['command']==='delete') {
            $this->loadAuthItem($_POST['id'])->delete();
            // reload the current page to avoid duplicated delete actions
            $this->refresh();
        }
    }

    private function _setMessage($mess) {
        Yii::app()->user->setState("message",$mess);
    }

    private function _getMessage() {
        return Yii::app()->user->getState("message");
    }

    public function actionAssignments() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $this->render('assignments');
        } else {
            throw new CHttpException(403,'You do not have authorization for this action',1);
        }
    }

    public function actionShowAssignments() {
        if(Yii::app()->user->checkAccess(Yii::app()->getModule('srbac')->superUser)|| !Helper::isAuthorizer()) {
            $userid = $_POST[Yii::app()->getModule('srbac')->userclass][$this->module->userid];
            $r = array(0=>array(0=>array()));
            if ($userid > 0) {
                $auth = Yii::app()->authManager;
        /* @var $auth CDbAuthManager */
                $ass = $auth->getAuthItems(2,$userid);
                $r= array();
                foreach ($ass as $i=>$role) {
                    $curRole = $role->name;
                    $r[$i]=$curRole;
                    $children = $auth->getItemChildren($curRole);
                    $r[$i]= array();
                    foreach ($children as $j=>$task) {
                        $curTask = $task->name;
                        $r[$i][$j]=$curTask;
                        $grandchildren = $auth->getItemChildren($curTask);
                        $r[$i][$j]= array();
                        foreach ($grandchildren as $k=>$oper) {
                            $curOper = $oper->name;
                            $r[$i][$j][$k]=$curOper;
                        }
                    }
                }
                $this->renderPartial('userAssignments', array('data'=>$r));
            }
        }
    }

}
